package com.edu.framework.websocket.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.edu.common.core.cache.ICache;
import com.edu.framework.websocket.WebSocketHolder;
import com.edu.framework.websocket.assemble.message.MessageAssemble;
import com.edu.framework.websocket.assemble.message.TriggerMsgEngine;
import com.edu.framework.websocket.message.base.Message;
import com.edu.framework.websocket.message.base.Response;
import com.edu.framework.websocket.message.close.CloseRequest;
import com.edu.framework.websocket.message.examseat.ExamSeatRequest;
import com.edu.framework.websocket.message.examseat.ExamSeatVO;
import com.edu.system.domain.TCard;
import com.edu.system.domain.TExamSeat;
import com.edu.system.mapper.ExamDetailMapper;
import com.edu.system.service.ITCardService;
import com.edu.system.service.ITExamMissService;
import com.edu.system.service.ITExamSeatService;
import com.edu.system.service.ITTerminalService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

/**
 * @program: xxxx
 * @description:
 * @author: zlh
 * @create: 2024-01-06 18:20
 **/
@Slf4j
@Component
public class ExamSeatService implements MessageAssemble {

  @Resource
  private ITExamSeatService itExamSeatService;
  @Resource
  private ITTerminalService itTerminalService;
  @Resource
  private ITCardService itCardService;
  @Resource
  private ICache iCache;

  private static final String CLOSE_ONCE_KEY = "closeOnce_examSeat_key_%s";


  private List<Long> seatIds = new ArrayList<>();

  public Response<ExamSeatVO> getSeat(Long classId) {
    if (classId == null){
      return null;
    }

    TExamSeat seat = new TExamSeat();
    seat.setClassId(classId);
    List<TExamSeat> tExamSeats = itExamSeatService.liveExamSeatList(seat);

    ExamSeatVO vo = Optional.ofNullable(tExamSeats)
        .filter(CollectionUtils::isNotEmpty)
        .map(a -> a.get(0).getExamSeat())
        .map(a -> JSONObject.parseObject(a, ExamSeatVO.class))
        .orElseGet(() -> null);

    String lockKey = String.format(CLOSE_ONCE_KEY, classId);

    if (vo == null){
      if (iCache.getCacheObject(lockKey) == "1"){
        return null;
      }
      // 打开 关闭锁
      iCache.setCacheObject(lockKey, "1");

      ExamSeatVO cVo = new ExamSeatVO();
      cVo.setCloseType(CloseRequest.EXAM_SEAT);
      return Response.ok(CloseRequest.TYPE, CloseRequest.RESP_KEY, cVo);
    }
    // 有强通知就，关掉 关闭锁
    iCache.setCacheObject(lockKey, "0");

    seatIds = tExamSeats.stream().map(TExamSeat::getId).collect(Collectors.toList());
    return Response.ok(ExamSeatRequest.TYPE, ExamSeatRequest.RESP_KEY, vo);
  }

  /**
   * 检查 卡号 或 密码是否合规有效
   * @param cardNo
   * @param password
   * @return
   */
  public String checkValid(String cardNo, String password){
    if (StrUtil.isBlank(cardNo) && StrUtil.isBlank(password)){
      return "请刷卡 或 输入密码";
    }
    if (StrUtil.isNotBlank(cardNo)){
      TCard card = itCardService.findCardByNo(cardNo);
      if (!card.getType().equals(1)){
        return "只允许教师卡登记缺考";
      }
    }
    if (StrUtil.isNotBlank(password)){
      TCard card2 = itCardService.findCardByOwnerId(password);
      if (Objects.isNull(card2)){
        return "密码输入错误";
      }
      if (!card2.getType().equals(1)){
        return "只允许教师卡登记缺考";
      }
    }

    return "";
  }

  /**
   * 编辑缺考
   * @param examSeatId
   * @param missIds
   * @return
   */
  public int editMissExam(Long examSeatId, List<Long> missIds){
    if (CollectionUtils.isEmpty(missIds)){
      return 0;
    }
    return itExamSeatService.editMissExam(examSeatId, missIds);
  }

  /**
   * 下发座位图
   * @param classIds
   * @throws IOException
   */
  public void pushMsg(List<Long> classIds) {
    Map<String, Long> codeMapId = itTerminalService.codeIdMapByLocationIds(null, "班牌");

    Function<String, Message> fc = code -> {
      Response<ExamSeatVO> vo = getSeat(codeMapId.getOrDefault(code, null));
      log.info("座位图：{}", JSONObject.toJSONString(vo));
      return vo;
    };
    Consumer<Message> invoke = message -> itExamSeatService.publishStatusToOn(this.seatIds);
    try {
//      WebSocketHolder.broadcastForCode(new ArrayList<>(codeMapId.keySet()), fc, invoke);
      WebSocketHolder.broadcast(fc, invoke);
    } catch (Exception e){
      log.error("主动下发失败 推送座位图", e);
    }

  }

  @Override
  public void buildTrigger(List<Long> firstClassIds) {
    TriggerMsgEngine.addEveryRun(ExamSeatService.class.getSimpleName());

//    Date date = new Date();
//    DateTime beginTime = DateUtil.beginOfDay(date);
//    DateTime endTime = DateUtil.endOfDay(date);
//
//    List<TExamSeat> seats = itExamSeatService.queryTodayChangeList();
//    String clsName = ExamSeatService.class.getSimpleName();
//    List<MsgCacheDTO> collect = seats.stream()
//        .flatMap(a -> {
//          List<MsgCacheDTO> d = new ArrayList<>();
//          if (a.getNoticeStartTime().after(beginTime) && a.getNoticeStartTime().before(endTime)) {
//            d.add(MsgCacheDTO.builder().triggerTime(a.getNoticeStartTime()).clsName(clsName).classIds(Arrays.asList(a.getClassId())).build());
//          }
//          if (a.getNoticeEndTime().after(beginTime) && a.getNoticeEndTime().before(endTime)) {
//            d.add(MsgCacheDTO.builder().triggerTime(a.getNoticeEndTime()).clsName(clsName).classIds(Arrays.asList(a.getClassId())).build());
//          }
//          return d.stream();
//        }).collect(Collectors.toList());
//    // 优先下发
//    if (CollectionUtils.isNotEmpty(firstClassIds)){
//      collect.add(MsgCacheDTO.builder().triggerTime(new Date()).clsName(clsName).classIds(firstClassIds).build());
//    }
//    // 装填
//    TriggerMsgEngine.addMsgDate(collect);
  }
}
